package com.ruoyi.web.controller;

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.common.business.entity.YytMember;
import com.ruoyi.common.business.service.YytMemberService;
import com.ruoyi.common.pms.entity.YytShopMember;
import com.ruoyi.common.pms.service.YytShopMemberService;
import com.ruoyi.utils.LoginParam;
import com.ruoyi.utils.RedisService;
import com.ruoyi.utils.ResponseResult;
import com.ruoyi.utils.SendSms;
import com.ruoyi.utils.WebConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName LoginController
 * @Description
 * @Author huangshun
 * @Date 2021/12/16 18:02
 */
@RequestMapping("member")
@RestController
public class LoginController {

    @Autowired
    private YytMemberService yytMemberService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private YytShopMemberService yytShopMemberService;


    /**
     * 方法名 login
     * 描述 TODO 用户名密码登录
     * 作者 黄顺
     * 时间 2021/12/16 20:23
     * @Param [loginParam, request]
     */
    @PostMapping("doLogin")
    public ResponseResult login(@RequestBody LoginParam loginParam, HttpServletRequest request){
        if(StringUtils.isEmpty(loginParam.getCodeKey())){
            return ResponseResult.failure("请输入验证码!");
        }
        Object code = redisService.get(loginParam.getCodeKey());
        if(code==null){
            return ResponseResult.failure("验证码已过期!");
        }
        String s = String.valueOf(code);
        if(!s.equals(loginParam.getCode())){
            return ResponseResult.failure("验证码不正确!");
        }

        LambdaQueryWrapper<YytMember> yytMemberLambdaQueryWrapper = new LambdaQueryWrapper<>();
        yytMemberLambdaQueryWrapper.eq(YytMember::getUsername,loginParam.getUserName()).eq(YytMember::getDelFlag,"0");
        YytMember member = yytMemberService.getOne(yytMemberLambdaQueryWrapper);
        // 用户不存在
        if(member==null){
            return ResponseResult.failure("用户名或密码不正确");
        }
        // 用户已停用
        if(member.getStatus().equals("1")){
            throw new DisableLoginException(request.getRemoteAddr(), member.getId(), System.currentTimeMillis());
        }
        // md5加盐加密: md5(md5(str) + md5(salt))
        String pwd = SaSecureUtil.md5BySalt(loginParam.getPassword(), member.getSalt());
        //认证成功
        if(member.getPassword().equals(pwd)) {
            StpUtil.login(member.getId(),loginParam.getSourceType());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            // 删除验证码缓存
            redisService.delete(loginParam.getCodeKey());
            //修改登录信息
            member.setLoginIp(request.getRemoteAddr());
            member.setLoginDate(LocalDateTime.now());
            yytMemberService.updateById(member);
            redisService.putNoTime(member.getId(), JSONUtil.toJsonPrettyStr(member));
            return ResponseResult.success(tokenInfo);
        }
        return ResponseResult.failure("用户名或密码不正确");
    }


    /**
     * 方法名 doPhoneLogin
     * 描述 TODO 手机号登录
     * 作者 黄顺
     * 时间 2021/12/16 20:51
     * @Param [loginParam, request]
     */
    @PostMapping("doPhoneLogin")
    public ResponseResult doPhoneLogin(@RequestBody LoginParam loginParam, HttpServletRequest request) {
        if(StringUtils.isEmpty(loginParam.getCodeKey())){
            return ResponseResult.failure("请输入验证码!");
        }
        Object code = redisService.get(loginParam.getCodeKey());
        if(code==null){
            return ResponseResult.failure("验证码已过期!");
        }
        String s = String.valueOf(code);
        if(!s.equals(loginParam.getCode())){
            return ResponseResult.failure("验证码不正确!");
        }

        LambdaQueryWrapper<YytMember> yytMemberLambdaQueryWrapper = new LambdaQueryWrapper<>();
        yytMemberLambdaQueryWrapper.eq(YytMember::getPhone,loginParam.getPhoneNumber()).eq(YytMember::getDelFlag,"0");
        YytMember member = yytMemberService.getOne(yytMemberLambdaQueryWrapper, false);
        // 用户不存在
        if(member==null){
            return ResponseResult.failure("用户不存在!");
        }
        // 用户已停用
        if(member.getStatus().equals("1")){
            throw new DisableLoginException(request.getRemoteAddr(), member.getId(), System.currentTimeMillis());
        }
        // 是否商户登录
        if(loginParam.getLoginStatus() == 1){
            QueryWrapper<YytShopMember> wrapper = new QueryWrapper<>();
            wrapper.eq("member_id", member.getId());
            int count = yytShopMemberService.count(wrapper);
            if (count == 0){
                return ResponseResult.failure("不是商户身份，请重新选择身份登录!");
            }
        }
        // 认证成功
        // 判断 用户 openId 是否一致, 不一致则更改
        if(!member.getWechatId().equals(loginParam.getWechatId())){
            // 修改用户 openId 数据
            QueryWrapper<YytMember> wrapper = new QueryWrapper<>();
            wrapper.eq("wechat_id", loginParam.getWechatId());
            YytMember yytMember = yytMemberService.getOne(wrapper);
            UpdateWrapper<YytMember> updateWrapper = new UpdateWrapper<>();
            if (yytMember != null){
                if(StringUtils.isNotBlank(yytMember.getNickname())){
                    updateWrapper.set("nickname", yytMember.getNickname());
                }
                if(StringUtils.isNotBlank(yytMember.getIcon())){
                    updateWrapper.set("icon", yytMember.getIcon());
                }
                yytMemberService.removeById(yytMember.getId());
            }
            //修改登录信息
            member.setLoginIp(request.getRemoteAddr());
            member.setLoginDate(LocalDateTime.now());
            updateWrapper.set("wechat_id", loginParam.getWechatId());
            updateWrapper.eq("id", member.getId());
            yytMemberService.update(updateWrapper);
        }else{
            //修改登录信息
            member.setLoginIp(request.getRemoteAddr());
            member.setLoginDate(LocalDateTime.now());
            yytMemberService.updateById(member);
        }
        StpUtil.login(member.getId(),loginParam.getSourceType());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 删除验证码缓存
        redisService.delete(loginParam.getCodeKey());


        redisService.putNoTime(member.getId(), JSONUtil.toJsonPrettyStr(member));
        return ResponseResult.success(tokenInfo);
    }


    /**
     * 方法名 isLogin
     * 描述 TODO 验证是否登录
     * 作者 黄顺
     * 时间 2021/12/16 20:22
     * @Param []
     */
    @GetMapping("isLogin")
    public ResponseResult isLogin() {
        return ResponseResult.success(StpUtil.isLogin());
    }

    /**
     * 方法名 logout
     * 描述 TODO 注销登录
     * 作者 黄顺
     * 时间 2021/12/16 20:22
     * @Param []
     */
    @GetMapping("logout")
    public ResponseResult logout() {
        String loginIdAsString = StpUtil.getLoginIdAsString();
        StpUtil.logout();
        redisService.delete(loginIdAsString);
        return ResponseResult.success("注销成功");
    }


    /**
     * 方法名 getCode
     * 描述 获取验证码
     * 作者 huangshun
     * 时间 2020/10/21 0021 下午 5:25
     * @Param [httpServletRequest, loginParamVO]
     */
    @GetMapping("getPhoneCode")
    public ResponseResult getPhoneCode(String phone,String temp){
        Map<String,Object> data=new HashMap<>();
        String codeKey = UUID.randomUUID().toString().replaceAll("-","");
        String code = WebConstants.generateNumber();
        data.put("codeKey", codeKey);
        //默认有效时间为5分钟
        int saveCodeTime = 5;
        //手机号获取时间
        Object saveTime = redisService.get(phone+"_"+temp);
        //不为空则验证时间
        if(saveTime!=null){
            long nowTime = System.currentTimeMillis();
            long value = Long.valueOf(saveTime.toString());
            long end  = nowTime - value;
            if(end < 60000){
                return ResponseResult.failure("请不要频繁操作!");
            }
        }
        //存到redis 中
        redisService.put(codeKey,code,saveCodeTime*60);
        //存储过期时间
        redisService.put(phone+"_"+temp,String.valueOf(System.currentTimeMillis()),60);
        List<String> phoneNumber = new ArrayList<>();
        phoneNumber.add("+86"+phone);
        List<String> templateParam= new ArrayList<>();
        // 随机
        templateParam.add(code);
        //时间
        templateParam.add(String.valueOf(saveCodeTime));
        //选择模板
        String templateID = "";
        //登录
        if(temp.equals("login")){
            templateID = WebConstants.TEMPLATEID_LOGIN;
        }
        //注册
        else if(temp.equals("register")){
            templateID = WebConstants.TEMPLATEID_REGISTER;
        }
        //重置密码
        else if(temp.equals("restpassword")){
            templateID = WebConstants.TEMPLATEID_RESTPASSWORD;
        }
        ConcurrentHashMap<String, Object> sendResilt =  SendSms.phoneSend(phoneNumber,templateParam,templateID);
        return ResponseResult.success("成功",data);
    }

}
